--CommonActionManager
--create by zouyb
--动作播放管理
--此处的动作泛指各种操作，比如执行几行代码，用一个callback函数包裹起来，也可以称之为一个"动作"

require "game/ui/base/CommonActionPhase"

-- CommonActionManager继承自Node
CommonActionManager = class("CommonActionManager", function()
    return cc.Node:create();
end);

function CommonActionManager.create(gridDesc)
    return CommonActionManager.new(gridDesc);
end

-- 构造函数
function CommonActionManager:ctor(gridDesc)
    self.gridDesc = gridDesc;

    self.gridList = {};
    self.actionList = {};
end

-- 播放动作列表中的动作
function CommonActionManager:play()
    if self.isPlaying then
        -- 已经在播放
        return;
    end

    if self:empty() then
        return;
    end

    if self:isPause() then
        return;
    end

    -- 播放一个动作
    local function doPlay()
        if self:empty() then
            return 0;
        end

        local actions = self:getNextActions();
        if actions == nil then
            return;
        end

        local action = actions[1];
        table.remove(actions, 1);

        self.isPlaying = true;

        local duration = catch(action.actionCallback, action.actionArgs) or 0;
        return duration, action.desc;
    end

    -- 依次播放所有动作
    local function playActions()
        if self.isPlaying then
           -- 上次的播放完毕
           EventMgr.fire(event.ONE_COMMON_ACTION_DONE);
        end

        if not self:empty() then
            local delay, desc = doPlay();
            self.lastDesc = desc;
            if delay == nil or delay <= 0 then
                playActions();
            else
                performWithDelay(self, playActions, delay);
            end
        else
            self.isPlaying = false;
        end
    end

    playActions();
end

-- 获取待处理的动作列表
function CommonActionManager:getNextActions()
    local num = 0;
    for _, actions in ipairs(self.actionList) do
        if #actions > 0 then
            return actions;
        end
    end

    return nil;
end

-- 暂停播放
function CommonActionManager:pause()
    self.isPausing = true;
end

-- 判断当前是否暂停
function CommonActionManager:isPause()
    return self.isPausing == true;
end

-- 继续播放
function CommonActionManager:continue()
    self.isPausing = false;
    self:play();
end

-- 是否有动作待播放
function CommonActionManager:empty()
    local num = #self.actionList;
    if num > 0 then
        num = 0;
        for _, actions in ipairs(self.actionList) do
            num = num + #actions;
            if (num > 0) then
                return false;
            end
        end
    end

    return true;
end

-- 是否完成所有动作
function CommonActionManager:isAllDone()
    local ret = self:empty() and not self.isPlaying;
    return ret;
end

-- 往尾部插入新的动作
function CommonActionManager:addAction(grid, actionCallback, desc, actionArgs, actionPhase)
    if type(grid) == 'function' then
        error("第一个参数传入有误")
        return;
    end

    if actionPhase == nil then
        error("目标阶段参数有误")
        return;
    end

    local targetActions;
    if grid == nil then
        -- 生成一个假的默认节点
        if self.defaultGrid == nil then
            self.defaultGrid  = Grid.new(0, 0, 0, GRID_STATE_COVER, {});
        end

        grid = self.defaultGrid;
    end

    local i = table.indexOf(self.gridList, grid);
    if i == -1 then
        table.insert(self.gridList, grid);
        table.insert(self.actionList, {});

        if #self.actionList > 2 then
            table.remove(self.actionList, 1);
            table.remove(self.gridList, 1);
        end
    end

    -- 再找一遍
    local i = table.indexOf(self.gridList, grid);
    targetActions = self.actionList[i];

    table.insert(targetActions, { actionCallback = actionCallback, actionArgs = actionArgs, phase = actionPhase, desc = desc });

    -- 按目标阶段排序
    local function sortAction(action1, action2)
        return action1.phase < action2.phase;
    end
    table.sort(targetActions, sortAction);
end

------------------------
-- 测试用
function testActionManager()
    require "game/ui/module/CommonActionManager"

    local actionMgr = CommonActionManager.create();
    UIMgr.getCurrentScene():addChild(actionMgr);

    local function delay()
        alert2("延迟三秒");
        return 0.1;
    end

    local function do1()
        alert2("开始1")
        return 0.2;
    end

    local function do2()
        alert2("开始2")
        return 0.3;
    end
    actionMgr:addAction(nil, delay, "delay", {}, 100);
    actionMgr:addAction(nil, do1, "do1", {}, 100);
    actionMgr:addAction(nil, do2, "do2", {}, 100);
    actionMgr:play();
end

